// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.core.resource;

import java.util.ArrayList;
import java.util.List;

import org.dengues.commons.utils.FileUtils;
import org.dengues.core.warehouse.ENodeCategoryName;
import org.dengues.core.warehouse.ENodeStatus;
import org.dengues.core.warehouse.IWarehouseNode;
import org.dengues.core.warehouse.IWarehouseObject;
import org.dengues.model.database.DatabaseDiagram;
import org.dengues.model.project.ProjectType;
import org.dengues.model.reports.Reports;
import org.dengues.model.warehouse.ProcessType;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.ecore.resource.Resource;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf 2007-12-5 qiang.zhang $
 * 
 */
public class WarehouseResourceFactory {

    private static DenguesResourceManager manager = new DenguesResourceManager();

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "create".
     * 
     * @param process
     * @param path
     */
    public static void create(ProcessType process, IPath path) {
        Resource itemResource = manager.createTypeResource(process, getProject(), path, ENodeCategoryName.PROCESS);
        itemResource.getContents().add(process);
        manager.saveResource(itemResource);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getProject".
     * 
     * @return
     */
    public static IProject getProject() {
        return DenguesProjectFactory.getDenguesProject().getProject();
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getObjectNamesFromEMF".
     * 
     * @param name
     * @param path
     * @param names
     */
    private static void getObjectNamesFromEMF(ENodeCategoryName name, IPath path, List<String> names) {
        List<Object> list = null;
        if (path.segmentCount() == 0) {
            list = getObjectFromEMF(name, path);
        } else {
            list = getObjectFromEMF(name, getProject().getFolder(path));
        }
        for (Object object : list) {
            if (object instanceof IFolder) {
                getObjectNamesFromEMF(name, ((IFolder) object).getProjectRelativePath(), names);
            }
            if (name == ENodeCategoryName.PROCESS && object instanceof ProcessType) {
                names.add(((ProcessType) object).getName());
            } else if (name == ENodeCategoryName.DATABASE && object instanceof DatabaseDiagram) {
                names.add(((DatabaseDiagram) object).getName());
            }
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getFolder".
     * 
     * @param name
     * @param relative
     * @return
     */
    public static IFolder getFolder(ENodeCategoryName name, IPath relative) {
        IFolder folder = manager.getFolder(getProject(), name, false);
        return folder.getFolder(relative);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getSubFolderNames".
     * 
     * @param name
     * @param parent
     * @return
     */
    public static List<String> getSubFolderNames(ENodeCategoryName name, IPath parent) {
        List<String> names = new ArrayList<String>();
        IFolder folder = manager.getFolder(getProject(), name, false);
        IFolder subFolder = folder.getFolder(parent);
        if (subFolder.exists()) {
            try {
                IResource[] members = folder.members();
                for (IResource resource : members) {
                    if (resource instanceof IFolder) {
                        IFolder file = (IFolder) resource;
                        names.add(file.getName());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return names;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getObjectFromEMF".
     * 
     * @param name
     * @param path
     * @return
     */
    public static List<Object> getObjectFromEMF(ENodeCategoryName name, IPath path) {
        IFolder folder = manager.getFolder(getProject(), name, false);
        folder = folder.getFolder(path);
        return getObjectFromEMF(name, folder);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getObjectFromEMF".
     * 
     * @param name
     * @param folder
     * @return
     */
    private static List<Object> getObjectFromEMF(ENodeCategoryName name, IFolder folder) {
        List<Object> list = new ArrayList<Object>();
        if (folder.exists()) {
            try {
                IResource[] members = folder.members();
                for (IResource resource : members) {
                    if (resource instanceof IFile) {
                        IFile file = (IFile) resource;
                        if (name == ENodeCategoryName.PROCESS) {
                            ProcessType processType = manager.loadProcess(file);
                            list.add(processType);
                        } else if (name == ENodeCategoryName.DATABASE) {
                            DatabaseDiagram loadDatabse = manager.loadDatabse(file);
                            list.add(loadDatabse);
                        } else if (name == ENodeCategoryName.REPORTS) {
                            Reports loadDatabse = manager.loadReports(file);
                            list.add(loadDatabse);
                        }
                    } else if (resource instanceof IFolder) {
                        list.add(resource);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getFileFromEMF".
     * 
     * @param type
     * @param name
     * @param path
     * @return
     */
    public static IFile getFileFromEMF(String type, ENodeCategoryName name, IPath path) {
        IFolder folder = manager.getFolder(getProject(), name, true);
        folder = folder.getFolder(path);
        try {
            IResource[] members = folder.members();
            for (IResource resource : members) {
                if (resource instanceof IFile) {
                    IFile file = (IFile) resource;
                    IPath fullPath = file.getFullPath();
                    String removeFileExtension = fullPath.removeFileExtension().segment(
                            fullPath.removeFileExtension().segmentCount() - 1);
                    String version = DenguesResourceManager.SEPERATOR + name.getVersion();
                    String simpleName = removeFileExtension.substring(0, removeFileExtension.indexOf(version));
                    if (simpleName.equals(type)) {
                        return file;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "save".
     * 
     * @param type
     */
    public static void save(ProcessType type) {
        Resource typeResource = manager.getTypeResource(type);
        typeResource.getContents().clear();
        typeResource.getContents().add(type);
        manager.saveResource(typeResource);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "save".
     * 
     * @param type
     */
    public static void save(ProjectType type) {
        Resource typeResource = manager.getTypeResource(type);
        typeResource.getContents().clear();
        typeResource.getContents().add(type);
        manager.saveResource(typeResource);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "save".
     * 
     * @param reports
     */
    public static void save(Reports reports) {
        Resource typeResource = manager.getTypeResource(reports);
        typeResource.getContents().clear();
        typeResource.getContents().add(reports);
        manager.saveResource(typeResource);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "save".
     * 
     * @param type
     */
    public static void save(DatabaseDiagram type) {
        Resource typeResource = manager.getTypeResource(type);
        typeResource.getContents().clear();
        typeResource.getContents().add(type);
        manager.saveResource(typeResource);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "create".
     * 
     * @param database
     * @param path
     */
    public static void create(DatabaseDiagram database, IPath path) {
        Resource itemResource = manager.createTypeResource(database, getProject(), path, ENodeCategoryName.DATABASE);
        itemResource.getContents().add(database);
        manager.saveResource(itemResource);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "deleteObjectPhysical".
     * 
     * @param object
     */
    public static void deleteObjectPhysical(IWarehouseObject object) {
        Object data = object.getData();
        List<Resource> resources = new ArrayList<Resource>();
        if (data instanceof DatabaseDiagram) {
            DatabaseDiagram type = ((DatabaseDiagram) data);
            resources = manager.getAffectedDatabases(type);
        } else if (data instanceof ProcessType) {
            ProcessType type = ((ProcessType) data);
            resources = manager.getAffectedProcesses(type);
        } else if (data instanceof Reports) {
            Reports type = (Reports) data;
            resources = manager.getAffectedReports(type);
        }
        for (Resource resource : resources) {
            manager.deleteResource(resource);
        }
    }

    public static void deleteObjectDataPhysical(Object data) {
        List<Resource> resources = new ArrayList<Resource>();
        if (data instanceof DatabaseDiagram) {
            DatabaseDiagram type = ((DatabaseDiagram) data);
            resources = manager.getAffectedDatabases(type);
        } else if (data instanceof ProcessType) {
            ProcessType type = ((ProcessType) data);
            resources = manager.getAffectedProcesses(type);
        }
        for (Resource resource : resources) {
            manager.deleteResource(resource);
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "deleteObjectLogical".
     * 
     * @param object
     */
    public static void deleteObjectLogical(IWarehouseObject object) {
        Object data = object.getData();
        if (data instanceof DatabaseDiagram) {
            DatabaseDiagram type = ((DatabaseDiagram) data);
            type.setStatus(ENodeStatus.DELETED.getId());
            WarehouseResourceFactory.save(type);
        } else if (data instanceof ProcessType) {
            ProcessType type = ((ProcessType) data);
            type.setStatus(ENodeStatus.DELETED.getId());
            WarehouseResourceFactory.save(type);
        } else if (data instanceof Reports) {
            Reports type = ((Reports) data);
            type.setStatus(ENodeStatus.DELETED.getId());
            WarehouseResourceFactory.save(type);
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "restoreObjectLogical".
     * 
     * @param object
     */
    public static void restoreObjectLogical(IWarehouseObject object) {
        Object data = object.getData();
        if (data instanceof DatabaseDiagram) {
            DatabaseDiagram type = ((DatabaseDiagram) data);
            type.setStatus(ENodeStatus.NORMAL.getId());
            WarehouseResourceFactory.save(type);
        } else if (data instanceof ProcessType) {
            ProcessType type = ((ProcessType) data);
            type.setStatus(ENodeStatus.NORMAL.getId());
            WarehouseResourceFactory.save(type);
        } else if (data instanceof Reports) {
            Reports type = (Reports) data;
            type.setStatus(ENodeStatus.NORMAL.getId());
            WarehouseResourceFactory.save(type);
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "moveObjectPhysical".
     * 
     * @param node
     * @param fullPath
     */
    public static void moveObjectPhysical(IWarehouseNode node, IPath fullPath) {
        IFolder folder = manager.getFolder(getProject(), node.getCategoryName(), false);
        IFile file = manager.getWarehouseFile(node);
        if (file.exists()) {
            IPath fullPath2 = file.getFullPath();
            IPath append = folder.getFile(fullPath).getProjectRelativePath().append(
                    fullPath2.segment(fullPath2.segmentCount() - 1));
            if (folder.getFile(append).exists()) {
                return;
            }
            String string = file.getProjectRelativePath().toString();
            String absolutePath = FileUtils.getRelativePath(append.toString(), string);
            try {
                file.move(new Path(absolutePath), false, null);
            } catch (CoreException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getAllObjectNamesFromEMF".
     * 
     * @param process
     * @return
     */
    public static List<String> getAllObjectNamesFromEMF(ENodeCategoryName process) {
        List<String> names = new ArrayList<String>();
        Path path = new Path(""); //$NON-NLS-1$
        getObjectNamesFromEMF(process, path, names);
        return names;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "create".
     * 
     * @param reports
     * @param path
     */
    public static void create(Reports reports, IPath path) {
        Resource itemResource = manager.createTypeResource(reports, getProject(), path, ENodeCategoryName.REPORTS);
        itemResource.getContents().add(reports);
        manager.saveResource(itemResource);
    }

}
